
# Thanks to Job Vranish (https://spin.atomicobject.com/2016/08/26/makefile-c-projects/)

# The default shell is /bin/sh. You can change this by changing the variable SHELL:
# SHELL=/bin/bash
# SHELL=/bin/sh

ROOT_DIR := .

PLATFORM := pan108

PROJ_NAME := ble_peripheral
# PROJ_NAME := ble_central
# PROJ_NAME := ble_multi_conn

ifeq ($(PLATFORM),pan108)
CFG := IP_108
endif
ifeq ($(PLATFORM), pan107)
CFG := IP_107
else
CFG := IP_108
endif
CFG := $(addprefix -D, $(CFG))

# LIBS = ble_pan108x_d
LIBS = $(wildcard lib/libble_pan108x_r.a) 
LIBS_PATH = $(ROOT_DIR)/lib

BIN_FILE = $(PROJ_NAME).elf
BIN = $(BUILD_DIR)/$(BIN_FILE)


# build folder
BUILD_DIR := $(ROOT_DIR)/BUILD

# Find all the C and C++ files we want to compile
# Note the single quotes around the * expressions. The shell will incorrectly expand these otherwise, but we want to send the * directly to the find command.
# SRCS := $(shell find . -name '*.cpp' -or -name '*.c' -or -name '*.s' -or -name '*.S')
SRCS := \
    $(wildcard $(ROOT_DIR)/*.c)\
	$(wildcard $(ROOT_DIR)/bsp/*.c)  \
	$(wildcard $(ROOT_DIR)/component/kv/*.c)  \
	$(wildcard $(ROOT_DIR)/component/spp/*.c)  \
	$(wildcard $(ROOT_DIR)/dfu/*.c)  \
	$(wildcard $(ROOT_DIR)/platform/$(PLATFORM)/src/*.c) \
	$(wildcard $(ROOT_DIR)/profile/*.c)  \
	$(wildcard $(ROOT_DIR)/spp/*.c)  \
	$(wildcard $(ROOT_DIR)/stack/controller/*.c) \
	$(wildcard $(ROOT_DIR)/stack/crypt/*.c) \
	$(wildcard $(ROOT_DIR)/stack/host/*.c) \
	$(wildcard $(ROOT_DIR)/utils/*.c) \
	$(wildcard $(ROOT_DIR)/project/$(PROJ_NAME)/*.c)     

ifeq ($(PLATFORM), pan108)
SRCS_ASM := $(wildcard $(ROOT_DIR)/cmsis/startup/startup_pan108x_gcc.S) 
endif
ifeq ($(PLATFORM), pan107)
SRCS_ASM := $(wildcard $(ROOT_DIR)/cmsis/startup/startup_pan107x_gcc.S)
else
SRCS_ASM := $(wildcard $(ROOT_DIR)/cmsis/startup/startup_pan108x_gcc.S) 
endif

# Linker Scripts path 
ifeq ($(PLATFORM),pan108)
LINKER_PATH := $(ROOT_DIR)/pan108x_new.ld
endif
ifeq ($(PLATFORM), pan107)
LINKER_PATH := $(ROOT_DIR)/pan107x_new.ld
else
LINKER_PATH := $(ROOT_DIR)/pan108x_new.ld
endif

# Prepends BUILD_DIR and appends .o to every src file
# As an example, ./your_dir/hello.cpp turns into ./build/./your_dir/hello.cpp.o
OBJS := $(SRCS:%.c=%.o) $(SRCS_ASM:%.S=%.o) 
OBJS := $(subst $(ROOT_DIR)/, $(BUILD_DIR)/, $(OBJS))


#SRCS_LIB := $(shell find ./stack -name '*.c')
#SRCS_LIB += $(shell find ./component/usb -name '*.c') 
SRCS_LIB :=
OBJS_LIB := $(SRCS_LIB:%=$(BUILD_DIR)/%.o)

# String substitution (suffix version without %).
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
DEPS := $(OBJS:.o=.d)

# Every folder in ./src will need to be passed to GCC so that it can find header files
# INC_DIRS := $(shell find $(SRC_DIRS) -maxdepth 3  -type d)
INC_DIRS := $(ROOT_DIR) $(ROOT_DIR)/platform/${PLATFORM}/inc  $(ROOT_DIR)/project/${PROJ_NAME} 
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I, $(INC_DIRS))


# Toolchain config --------------------------------------------
CROSS_COMPILE := arm-none-eabi-

CXX ?=
CC  := ${CROSS_COMPILE}gcc
CXX := ${CROSS_COMPILE}g++
LD  := ${CROSS_COMPILE}gcc
AR  := ${CROSS_COMPILE}ar

# For Embedded
OBJCOPY := ${CROSS_COMPILE}objcopy -O binary
OBJDUMP := ${CROSS_COMPILE}objdump --source --all-headers --demangle --file-headers --syms --wide
OBJSIZE := ${CROSS_COMPILE}size 

# The -MMD and -MP flags together generate Makefiles for us!
# These files will have .d instead of .o as the output.
CPP_FLAGS := $(INC_FLAGS) -MMD -MP
# CPP_FLAGS := $(INC_FLAGS) -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" 

# Options for release
C_FLAGS  := -mcpu=cortex-m0 -mthumb -O2 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g \
            $(CFG)

# Options for linker
LD_FLAGS := -mcpu=cortex-m0 -mthumb -O2 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g\
			-nostartfiles -Xlinker --gc-sections -Wl,-Map,"$(BUILD_DIR)/$(PROJ_NAME).map" \
			--specs=nano.specs --specs=nosys.specs -Wl,--no-warn-rwx-segments -T $(LINKER_PATH) 

all: $(BIN) show.options
	@echo "+++ Toolchain"
	@$(CC) --version | head -n 1

$(BIN): $(OBJS) $(LIBS) 
	@echo "+++ Linking: $@"
	@$(LD) $(LD_FLAGS) -o $(BIN) $(OBJS) $(LIBS) 
	@$(OBJCOPY) -O binary $(BIN) $(BIN:.elf=.bin)
	@$(OBJCOPY) -O ihex $(BIN) $(BIN:.elf=.hex)
	@$(OBJDUMP) -t $(BIN) > $(BIN:.elf=.lst)
	@echo "+++ Binary summary: $(BIN)"
	@-$(OBJSIZE) $(BIN)
	@echo "+++ Section summary: $(BIN:.elf=.map)"
	@grep ^.text $(BIN:.elf=.map) | awk '{print "    " $$3 "\t" $$1}'
	@grep ^.bss  $(BIN:.elf=.map) | awk '{print "    " $$3 "\t" $$1}'
	@grep ^.data $(BIN:.elf=.map) | awk '{print "    " $$3 "\t" $$1}'

# Build step for C source
$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.c 
	@echo "+++ Building: $(<) "
	@mkdir -p $(dir $@)
	@$(CC) $(CPP_FLAGS) $(C_FLAGS) -c $< -o $@

# Build step for C++ source
$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.cpp
	@echo "+++ Building: $(<F)"
	@mkdir -p $(dir $@)
	@$(CXX) $(CPP_FLAGS) $(CXXFLAGS) -c $< -o $@

# Build step for C source
$(BUILD_DIR)/%.o: $(ROOT_DIR)/%.S
	@echo "+++ Building: $(<)"
	@mkdir -p $(dir $@)
	@$(CC) $(CPP_FLAGS) $(C_FLAGS) -c $< -o $@
	
# Include the .d makefiles. The - at the front suppresses the errors of missing
# Makefiles. Initially, all the .d files will be missing, and we don't want those
# errors to show up.
-include $(DEPS)


clean:
	@-rm -rf $(BUILD_DIR)
	@echo "Clean done ..."
	
clean_lib:
	@-rm -rf $(BUILD_DIR)/$(TARGET_LIB).a
	@echo "Clean lib done ..."
	
show.options:
	@echo "+++ Build options"
	@echo "    PROJ_NAME            = $(PROJ_NAME)"
	@echo "    PLATFORM             = $(PLATFORM)"
	@echo "    CFG                  = $(CFG)"
#	@echo "    LD_FLAGS             = $(LD_FLAGS)"
#	@echo "    INC_DIRS             = $(INC_DIRS)"
	
help:
	@:
	${info Help}
	${info -------------------------------------------------------}
	${info make help                          - this help text}
	${info make all                           - compile binary}
	${info make lib                           - assemble library}
	${info make clean                         - clean}
	${info make clean_lib                     - clean lib files}
	${info -------------------------------------------------------}

.PHONY: all clean clean_lib help 
.PHONY: show.options
